using Jupiter.Infrastructure;
using Jupiter.Infrastructure.Cache.Interfaces;
using Jupiter.Infrastructure.Domain;
using Jupiter.Infrastructure.Domain.SqlSugar;
using Jupiter.Infrastructure.Domain.SqlSugar.Basic;
using Jupiter.Infrastructure.Exceptions;
using Jupiter.Infrastructure.Mappings;
using Jupiter.Infrastructure.Permission;
using Jupiter.Infrastructure.Permission.DataPermissions;
using MediatR;
using Microsoft.Extensions.Configuration;
using Wips.AppService.Authorities.Positions.Requests;
using Wips.Domain.Models.Authorities.Model;

namespace Wips.AppService.SqlSugar.Authorities.Positions
{
    /// <summary>
    /// 职位请求处理程序
    /// </summary>
    public class PositionRequestHandler :
        RequestHandlerBase<Position>,
        IRequestHandler<CreatePositionRequest, string>,
        IRequestHandler<UpdatePositionRequest, string>,
        IRequestHandler<DeletePositionRequest, string>,
        IRequestHandler<AssignRolesForPositionRequest, string>,
        IRequestHandler<PositionStatusChangeRequest, string>
    {
        private readonly IMapsterMapper _mapper;


        /// <summary>
        /// 创建
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<string> Handle(CreatePositionRequest request,
            CancellationToken cancellationToken)
        {
            // 封装实体对象
            var entity = _mapper.MapTo<Position>(request);
            entity.Id = ObjectId.GenerateNewStringId();
            entity.CreatorId = UserId!;
            entity.LastUpdatedUserId = UserId;
            if (request.ParentId != null)
            {
                entity.ParentPath = await GetParentPathAsync(request.ParentId, cancellationToken);
            }

            await RegisterNewAsync(entity, cancellationToken);

            // 新增关联数据
            if (request.RoleIds.Count > 0)
            {
                await RegisterNewObjectValueRangeAsync(
                    request
                        .RoleIds
                        .Select(roleId => new PositionRole(entity.Id, roleId))
                        .ToList()
                    , cancellationToken
                );
            }

            // 提交

            return entity.Id;
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<string> Handle(UpdatePositionRequest request,
            CancellationToken cancellationToken)
        {
            if (request.ParentId == request.Id)
            {
                throw new CoreException("不能选择自己作为上级");
            }


            // 封装实体对象
            var entity = await Query()
                .FirstOrDefaultAsync(p => p.Id == request.Id, cancellationToken);

            if (entity == null)
            {
                throw new CoreException("找不到记录");
            }

            var parentPath = "";
            if (request.ParentId != null)
            {
                parentPath = await GetParentPathAsync(request.ParentId, cancellationToken);
            }

            // 更新
            entity.Update(request.ParentId, parentPath, request.Name, request.Remarks, UserId);
            // 更新
            RegisterDirty(entity);

            // 删除旧数据
            RegisterDeleteObjectValueRange<PositionRole>(p => p.PositionId == entity.Id);

            // 新增关联数据
            if (request.RoleIds.Count > 0)
            {
                var positionRoles = request
                    .RoleIds
                    .Select(roleId => new PositionRole(entity.Id, roleId))
                    .ToList();
                // 批量新增
                await RegisterNewObjectValueRangeAsync(positionRoles, cancellationToken: cancellationToken);
            }

            // 提交

            return entity.Id!;
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="CoreException"></exception>
        public async Task<string> Handle(DeletePositionRequest request,
            CancellationToken cancellationToken)
        {
            // 封装实体对象
            var entity = await Query()
                .FirstOrDefaultAsync(p => p.Id == request.Id, cancellationToken);
            if (entity == null)
            {
                throw new CoreException("找不到要删除的数据");
            }

            // 删除
            RegisterDelete(entity);
            return entity.Id!;
        }

        /// <summary>
        /// 分配角色
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="CoreException"></exception>
        public async Task<string> Handle(AssignRolesForPositionRequest request,
            CancellationToken cancellationToken)
        {
            var entity = await Query()
                .FirstOrDefaultAsync(p => p.Id == request.PositionId, cancellationToken);
            if (entity == null)
            {
                throw new CoreException("找不到职位信息");
            }

            // 读取旧的职位角色关联数据
            RegisterDeleteObjectValueRange<PositionRole>(p => p.PositionId == request.PositionId);


            // 创建新的关联数据
            var news = request
                .RoleIds
                .Select(roleId => new PositionRole(request.PositionId, roleId))
                .ToList();
            // 批量新增
            await RegisterNewObjectValueRangeAsync(news, cancellationToken: cancellationToken);
            // 提交


            return entity.Id!;
        }

        /// <summary>
        /// 状态变更
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<string> Handle(PositionStatusChangeRequest request,
            CancellationToken cancellationToken)
        {
            // 封装实体对象
            var entity = await Query()
                .FirstOrDefaultAsync(p => p.Id == request.Id, cancellationToken);

            if (entity == null)
            {
                throw new CoreException("找不到记录");
            }

            // 变更状态
            entity.StatusChange(UserId);
            // 更新
            RegisterDirty(entity);

            return entity.Id!;
        }

        #region 私有方法

        /// <summary>
        /// 读取ParentPath
        /// </summary>
        /// <param name="parentId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="CoreException"></exception>
        private async Task<string> GetParentPathAsync(string parentId, CancellationToken cancellationToken = default)
        {
            // 读取上级信息
            var parent = await QueryNoTracking()
                .FirstOrDefaultAsync(p => p.Id == parentId, cancellationToken);

            if (parent == null)
            {
                throw new CoreException("找不到上级菜单");
            }

            return string.IsNullOrEmpty(parent.ParentPath)
                ? parentId
                : $"{parent.ParentPath},{parentId}";
        }

        #endregion


        /// <summary>
        /// 
        /// </summary>
        /// <param name="dbContext"></param>
        /// <param name="securityContextAccessor"></param>
        /// <param name="facadeResolver"></param>
        /// <param name="cacheManager"></param>
        /// <param name="configuration"></param>
        /// <param name="mapper"></param>
        /// <param name="dataPermission"></param>
        public PositionRequestHandler(ISqlSugarClient dbContext, ISecurityContextAccessor securityContextAccessor,
            IFacadeResolver facadeResolver, ICacheManager cacheManager, IConfiguration configuration,
            IMapsterMapper mapper, IDataPermission dataPermission) : base(
            dbContext, securityContextAccessor, facadeResolver, cacheManager, configuration, dataPermission)
        {
            _mapper = mapper;
        }
    }
}